import 'dart:math';

import 'package:al_utils/al_utils.dart';

extension DateExtension on DateTime {

  static const kDefaultFormat = 'yyyy/MM/dd HH:mm:ss';

  String getWeekday() {
    return ['', '一', '二', '三', '四', '五', '六', '日'][weekday];
  }

  String format({String format = kDefaultFormat}) {
    String result = format;
    // format year text
    if (format.contains('y')) {
      result = DateTimeFormatter._formatYear(year, result);
    }
    // format month text
    if (format.contains('M')) {
      result = DateTimeFormatter._formatMonth(month, result);
    }
    // format day text
    if (format.contains('d')) {
      result = DateTimeFormatter._formatDay(day, result);
    }
    if (format.contains('E')) {
      result = DateTimeFormatter._formatWeek(weekday, result);
    }

    if (format.contains('H')) {
      result = DateTimeFormatter._formatHour(hour, result);
    }
    // format minute text
    if (format.contains('m')) {
      result = DateTimeFormatter._formatMinute(minute, result);
    }
    // format second text
    if (format.contains('s')) {
      result = DateTimeFormatter._formatSecond(second, result);
    }

    if (result == format) {
      return toString();
    }
    return result;
  }

  DateTime get firstSecond {
    return DateTime(year, month, day);
  }
}

const String DATE_FORMAT_SEPARATOR = r'[/|,-\._: ]+';

class DateTimeFormatter {
  static bool isDayFormat(String format) {
    return format.contains(RegExp(r'[yMdE]'));
  }

  static bool isTimeFormat(String format) {
    return format.contains(RegExp(r'[Hms]'));
  }


  static DateTime datetimeFromString(String? date) {
    if (date.or().isEmpty) return DateTime.now();
    return DateTime.parse(date!.replaceAll('/', '-'));
  }

  static String formatDateTime(int value, String format) {
    // return DateTime.fromMillisecondsSinceEpoch(value).format(format: format);

    if (format.isEmpty) {
      return value.toString();
    }

    String result = format;
    // format year text
    if (format.contains('y')) {
      result = _formatYear(value, result);
    }
    // format month text
    if (format.contains('M')) {
      result = _formatMonth(value, result);
    }
    // format day text
    if (format.contains('d')) {
      result = _formatDay(value, result);
    }
    if (format.contains('E')) {
      result = _formatWeek(value, result);
    }
    // format hour text
    if (format.contains('H')) {
      result = _formatHour(value, result);
    }
    // format minute text
    if (format.contains('m')) {
      result = _formatMinute(value, result);
    }
    // format second text
    if (format.contains('s')) {
      result = _formatSecond(value, result);
    }
    if (result == format) {
      return value.toString();
    }
    return result;
  }

  // static String formatDate(DateTime? dateTime, {String format = Constant.datetimeFormat}) {
  //   if (dateTime == null) return '';
  //   if (format.contains('yy')) {
  //     String year = dateTime.year.toString();
  //     if (format.contains('yyyy')) {
  //       format = format.replaceAll('yyyy', year);
  //     } else {
  //       format = format.replaceAll(
  //           'yy', year.substring(year.length - 2, year.length));
  //     }
  //   }
  //
  //   format = _comFormat(dateTime.month, format, 'M', 'MM');
  //   format = _comFormat(dateTime.day, format, 'd', 'dd');
  //   format = _comFormat(dateTime.hour, format, 'H', 'HH');
  //   format = _comFormat(dateTime.minute, format, 'm', 'mm');
  //   format = _comFormat(dateTime.second, format, 's', 'ss');
  //   format = _comFormat(dateTime.millisecond, format, 'S', 'SSS');
  //
  //   return format;
  // }
  //
  // /// com format.
  // static String _comFormat(
  //     int value, String format, String single, String full) {
  //   if (format.contains(single)) {
  //     if (format.contains(full)) {
  //       format =
  //           format.replaceAll(full, value < 10 ? '0$value' : value.toString());
  //     } else {
  //       format = format.replaceAll(single, value.toString());
  //     }
  //   }
  //   return format;
  // }

  /// Format day display
  static String formatDate(DateTime dateTime, {String format = 'yyyy/MM/dd HH:mm:ss'}) {
    return dateTime.format(format: format);
  }

  /// format year text
  static String _formatYear(int value, String format) {
    if (format.contains('yyyy')) {
      // yyyy: the digit count of year is 4, e.g. 2019
      return format.replaceAll('yyyy', value.toString());
    } else if (format.contains('yy')) {
      // yy: the digit count of year is 2, e.g. 19
      return format.replaceAll('yy', value.toString().substring(max(0, value.toString().length - 2)));
    }
    return value.toString();
  }

  /// format month text
  static String _formatMonth(int value, String format) {
    List<String> months = ['01', '02', '03', '04', '05', '06', '07', '08', '09', '10', '11', '12'];
    if (format.contains('MMMM')) {
      // MMMM: the full name of month, e.g. January
      return format.replaceAll('MMMM', months[value - 1]);
    } else if (format.contains('MMM')) {
      // MMM: the short name of month, e.g. Jan
      String month = months[value - 1];
      return format.replaceAll('MMM', month.substring(0, min(3, month.length)));
    }
    return _formatNumber(value, format, 'M');
  }

  /// format day text
  static String _formatDay(int value, String format) {
    return _formatNumber(value, format, 'd');
  }

  /// format week text
  static String _formatWeek(int value, String format) {
    if (format.contains('EEEE')) {
      // EEEE: the full name of week, e.g. Monday
      List<String> weeks = ['周一', '周二', '周三', '周四', '周五', '周六', '周日'];
      return format.replaceAll('EEEE', weeks[value - 1]);
    }
    // EEE: the short name of week, e.g. Mon
    List<String> weeks = ['周一', '周二', '周三', '周四', '周五', '周六', '周日'];
    return format.replaceAll(RegExp(r'E+'), weeks[value - 1]);
  }

  /// format hour text
  static String _formatHour(int value, String format) {
    return _formatNumber(value, format, 'H');
  }

  /// format minute text
  static String _formatMinute(int value, String format) {
    return _formatNumber(value, format, 'm');
  }

  /// format second text
  static String _formatSecond(int value, String format) {
    return _formatNumber(value, format, 's');
  }

  /// format number, if the digit count is 2, will pad zero on the left
  static String _formatNumber(int value, String format, String unit) {
    if (format.contains('$unit$unit')) {
      return format.replaceAll('$unit$unit', value.toString().padLeft(2, '0'));
    } else if (format.contains(unit)) {
      return format.replaceAll(unit, value.toString());
    }
    return value.toString();
  }
}
